package ru.mirent.json;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.Map;

public class ObjectToJsonTest {
    private final String innerJson = "{\"key1\":\"Элемент вложенного Json 1\",\"key2\":\"Элемент вложенного Json 2\",\"key3\":\"Элемент вложенного Json 3\"}";

    /**
     * Пример преобразования Json в виде текста.
     */
    @Test
    void jsonTest() {
        String expected = "{" + System.lineSeparator() +
                "  \"key1\" : \"Элемент вложенного Json 1\"," + System.lineSeparator() +
                "  \"key2\" : \"Элемент вложенного Json 2\"," + System.lineSeparator() +
                "  \"key3\" : \"Элемент вложенного Json 3\"" + System.lineSeparator() +
                "}";

        ObjectToJson objectToJson = new ObjectToJson();
        String actual = objectToJson.apply(innerJson);
        System.out.println(actual);
        Assertions.assertEquals(expected, actual);
    }

    /**
     * Пример преобразования Json вложенного в List.
     */
    @Test
    void listTest() {
        String expected = "[" + System.lineSeparator() +
                "  {" + System.lineSeparator() +
                "    \"key1\" : \"Элемент вложенного Json 1\"," + System.lineSeparator() +
                "    \"key2\" : \"Элемент вложенного Json 2\"," + System.lineSeparator() +
                "    \"key3\" : \"Элемент вложенного Json 3\"" + System.lineSeparator() +
                "  }" + System.lineSeparator() +
                "]";

        ObjectToJson objectToJson = new ObjectToJson();
        String actual = objectToJson.apply(List.of(innerJson));
        System.out.println(actual);
        Assertions.assertEquals(expected, actual);
    }

    /**
     * Пример преобразования Json вложенного в Map.
     */
    @Test
    void mapTest() {
        String expected = "{" + System.lineSeparator() +
                "  \"map\" : {" + System.lineSeparator() +
                "    \"key1\" : \"Элемент вложенного Json 1\"," + System.lineSeparator() +
                "    \"key2\" : \"Элемент вложенного Json 2\"," + System.lineSeparator() +
                "    \"key3\" : \"Элемент вложенного Json 3\"" + System.lineSeparator() +
                "  }" + System.lineSeparator() +
                "}";

        ObjectToJson objectToJson = new ObjectToJson();
        String actual = objectToJson.apply(Map.of("map", innerJson));
        System.out.println(actual);
        Assertions.assertEquals(expected, actual);
    }

    /**
     * Пример преобразования Json вложенного в значение параметра класса с получением по геттеру.
     */
    @Test
    void exampleGetterTest() {
        String expected = "{" + System.lineSeparator() +
                "  \"getterValue\" : {" + System.lineSeparator() +
                "    \"key1\" : \"Элемент вложенного Json 1\"," + System.lineSeparator() +
                "    \"key2\" : \"Элемент вложенного Json 2\"," + System.lineSeparator() +
                "    \"key3\" : \"Элемент вложенного Json 3\"" + System.lineSeparator() +
                "  }" + System.lineSeparator() +
                "}";

        ObjectToJson objectToJson = new ObjectToJson();
        ExampleGetter exampleGetter = new ExampleGetter(innerJson);
        String actual = objectToJson.apply(exampleGetter);
        System.out.println(actual);
        Assertions.assertEquals(expected, actual);
    }

    /**
     * Пример преобразования Json вложенного в значение параметра класса с получением по полю.
     */
    @Test
    void exampleFieldTest() {
        String expected = "{" + System.lineSeparator() +
                "  \"fieldValue\" : {" + System.lineSeparator() +
                "    \"key1\" : \"Элемент вложенного Json 1\"," + System.lineSeparator() +
                "    \"key2\" : \"Элемент вложенного Json 2\"," + System.lineSeparator() +
                "    \"key3\" : \"Элемент вложенного Json 3\"" + System.lineSeparator() +
                "  }" + System.lineSeparator() +
                "}";

        ObjectToJson objectToJson = new ObjectToJson();
        ExampleField exampleGetter = new ExampleField(innerJson);
        String actual = objectToJson.apply(exampleGetter);
        System.out.println(actual);
        Assertions.assertEquals(expected, actual);
    }

    static class ExampleGetter {
        private final String getterValue;

        public ExampleGetter(String getterValue) {
            this.getterValue = getterValue;
        }

        public String getGetterValue() {
            return getterValue;
        }
    }

    static class ExampleField {
        private final String fieldValue;

        public ExampleField(String fieldValue) {
            this.fieldValue = fieldValue;
        }
    }
}
